package com.sunday.study.classify;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @Description: aop五种通知类型
 * <p>
 * //前置通知：在方法执行前通知
 * @Before(value = “”)
 * //环绕通知：可以将要执行的方法（point.proceed()）进行包裹执行，可以在前后添加需要执行的操作
 * @Around(value = “”)
 * //后置通知：在方法正常执行完成进行通知，可以访问到方法的返回值的。
 * @AfterReturning(value = “”)
 * //异常通知：在方法出现异常时进行通知,可以访问到异常对象，且可以指定在出现特定异常时在执行通知。
 * @AfterThrowing(value = “”)
 * //方法执行后通知： 在目标方法执行后无论是否发生异常，执行通知,不能访问目标方法的执行的结果。
 * @After(value = “”)
 * 注意区分@After和@AfterReturning区别，After不论方法是否执正常结束都会通知，而AfterReturning出现异常未正常结束则不会通知。
 * @Author: zsy
 * @Create: 2022/12/8 15:47
 */
@Slf4j
@Component
@Aspect
public class AopClassify {

    /****************************    save   **********************************/

    @Pointcut("execution(* com.sunday.study.classify.dao.CommodityDao.save())")
    public void pt() {
    }

    //@Before：前置通知，在原始方法运行之前执行
    @Before("pt()")
    public void before() {
        log.info("before advice ...");
    }

    //@After：后置通知，在原始方法运行之后执行
    @After("pt()")
    public void after() {
        log.info("after advice ...");
    }

    //@Around：环绕通知，在原始方法运行的前后执行
    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        log.info("around before advice ...");
        //表示对原始操作的调用
        Object ret = pjp.proceed();
        log.info("around after advice ...");
        return ret;
    }

    /****************************    remove   **********************************/

    @Pointcut("execution(* com.sunday.study.classify.dao.CommodityDao.remove())")
    public void pt2() {
    }

    //@Before：前置通知，在原始方法运行之前执行
    @Before("pt2()")
    public void before2() {
        log.info("before advice ...");
    }

    //@After：后置通知，在原始方法运行之后执行
    @After("pt2()")
    public void after2() {
        log.info("after advice ...");
    }

    //@Around：环绕通知，在原始方法运行的前后执行
    @Around("pt2()")
    public Object around2(ProceedingJoinPoint pjp) throws Throwable {
        log.info("around before advice ...");
        //表示对原始操作的调用
        Object ret = pjp.proceed();
        log.info("around after advice ...");
        return ret;
    }

    //@AfterReturning：返回后通知，在原始方法执行完毕后运行，且原始方法执行过程中未出现异常现象
    @AfterReturning("pt2()")
    public void afterReturning2() {
        log.info("afterReturning advice ...");
    }

    //@AfterThrowing：抛出异常后通知，在原始方法执行过程中出现异常后运行
    @AfterThrowing("pt2()")
    public void afterThrowing2() {
        log.info("afterThrowing advice ...");
    }

    /****************************    update   **********************************/

    @Pointcut("execution(* com.sunday.study.classify.dao.CommodityDao.update())")
    public void pt3() {
    }

    //@Before：前置通知，在原始方法运行之前执行
    @Before("pt3()")
    public void before3() {
        log.info("before advice ...");
    }

    //@After：后置通知，在原始方法运行之后执行
    @After("pt3()")
    public void after3() {
        log.info("after advice ...");
    }

    //@Around：环绕通知，在原始方法运行的前后执行
    @Around("pt3()")
    public Object around3(ProceedingJoinPoint pjp) throws Throwable {
        try {
            log.info("around before advice ...");
            //表示对原始操作的调用
            Object ret = pjp.proceed();
            log.info("around after advice ...");
            return ret;
        }catch (Exception e){
            log.info("{}",e.toString());
        }
        return null;
    }

    //@AfterReturning：返回后通知，在原始方法执行完毕后运行，且原始方法执行过程中未出现异常现象
    @AfterReturning("pt3()")
    public void afterReturning3() {
        log.info("afterReturning advice ...");
    }

    //@AfterThrowing：抛出异常后通知，在原始方法执行过程中出现异常后运行
    @AfterThrowing("pt3()")
    public void afterThrowing3() {
        log.info("afterThrowing advice ...");
    }

}
